package cn.shengchao.examstar.ai.domain.model;

import cn.shengchao.examstar.ai.domain.event.StudyProgressUpdatedEvent;
import cn.shengchao.examstar.ai.domain.exception.InvalidStudyPlanException;
import cn.shengchao.examstar.ai.domain.model.studyplan.StudyPlanId;
import cn.shengchao.examstar.ai.domain.valueobject.*;
import cn.shengchao.examstar.shared.domain.event.DomainEvent;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 学习计划聚合根
 * 领域实体，包含业务逻辑和行为
 * 管理完整的学习计划生命周期
 */
@Getter
public class StudyPlan {
    
    private StudyPlanId id;
    private UserId userId;
    private SpecificationType specificationType;
    private DegreeOfMastery degreeOfMastery;
    private StudyDuration dailyStudyDuration;
    private StudyPeriod studyPeriod;
    private String studyAdvice;
    private StudyPlanStatus status;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    
    // 领域事件列表
    private final List<DomainEvent> domainEvents = new ArrayList<>();
    
    // 私有构造函数，强制通过工厂方法创建
    private StudyPlan() {}
    
    /**
     * 创建学习计划
     */
    public static StudyPlan create(SpecificationType specificationType, 
                                  UserId userId,
                                  DegreeOfMastery degreeOfMastery,
                                  StudyDuration dailyStudyDuration,
                                  StudyPeriod studyPeriod,
                                  String studyAdvice) {
        
        validateCreationParameters(specificationType, userId, degreeOfMastery, 
                                 dailyStudyDuration, studyPeriod);
        
        StudyPlan studyPlan = new StudyPlan();
        studyPlan.id = StudyPlanId.generate(); // 新创建时ID为null，由持久化层生成
        studyPlan.specificationType = specificationType;
        studyPlan.userId = userId;
        studyPlan.degreeOfMastery = degreeOfMastery;
        studyPlan.dailyStudyDuration = dailyStudyDuration;
        studyPlan.studyPeriod = studyPeriod;
        studyPlan.studyAdvice = studyAdvice;
        studyPlan.status = StudyPlanStatus.DRAFT;
        studyPlan.createTime = LocalDateTime.now();
        studyPlan.updateTime = LocalDateTime.now();
        
        return studyPlan;
    }
    
    /**
     * 从持久化对象重建领域对象
     */
    public static StudyPlan fromPersistence(StudyPlanId id,
                                           SpecificationType specificationType,
                                           UserId userId,
                                           DegreeOfMastery degreeOfMastery,
                                           StudyDuration dailyStudyDuration,
                                           StudyPeriod studyPeriod,
                                           String studyAdvice,
                                           StudyPlanStatus status,
                                           LocalDateTime createTime,
                                           LocalDateTime updateTime) {
        StudyPlan studyPlan = new StudyPlan();
        studyPlan.id = id;
        studyPlan.specificationType = specificationType;
        studyPlan.userId = userId;
        studyPlan.degreeOfMastery = degreeOfMastery;
        studyPlan.dailyStudyDuration = dailyStudyDuration;
        studyPlan.studyPeriod = studyPeriod;
        studyPlan.studyAdvice = studyAdvice;
        studyPlan.status = status != null ? status : StudyPlanStatus.DRAFT;
        studyPlan.createTime = createTime;
        studyPlan.updateTime = updateTime;
        
        return studyPlan;
    }
    
    /**
     * 更新掌握程度
     */
    public void updateDegreeOfMastery(DegreeOfMastery newDegree) {
        if (newDegree == null) {
            throw new IllegalArgumentException("掌握程度不能为空");
        }
        
        if (!status.canModify()) {
            throw InvalidStudyPlanException.businessRuleViolation(
                "学习计划状态为" + status.getName() + "，不允许修改掌握程度");
        }
        
        DegreeOfMastery oldDegree = this.degreeOfMastery;
        this.degreeOfMastery = newDegree;
        this.updateTime = LocalDateTime.now();
        
        // 发布进度更新事件
        addDomainEvent(new StudyProgressUpdatedEvent(this.id, this.userId, oldDegree, newDegree));
    }
    
    /**
     * 调整学习时长
     */
    public void adjustStudyDuration(StudyDuration newDuration) {
        if (newDuration == null) {
            throw new IllegalArgumentException("学习时长不能为空");
        }
        
        if (!status.canModify()) {
            throw InvalidStudyPlanException.businessRuleViolation(
                "学习计划状态为" + status.getName() + "，不允许调整学习时长");
        }
        this.dailyStudyDuration = newDuration;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 开始学习计划
     */
    public void start() {
        if (!status.canTransitionTo(StudyPlanStatus.ACTIVE)) {
            throw InvalidStudyPlanException.invalidStateTransition(status.getName(), StudyPlanStatus.ACTIVE.getName());
        }
        
        this.status = StudyPlanStatus.ACTIVE;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 暂停学习计划
     */
    public void pause() {
        if (!status.canTransitionTo(StudyPlanStatus.PAUSED)) {
            throw InvalidStudyPlanException.invalidStateTransition(status.getName(), StudyPlanStatus.PAUSED.getName());
        }
        
        this.status = StudyPlanStatus.PAUSED;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 完成学习计划
     */
    public void complete() {
        if (!status.canTransitionTo(StudyPlanStatus.COMPLETED)) {
            throw InvalidStudyPlanException.invalidStateTransition(status.getName(), StudyPlanStatus.COMPLETED.getName());
        }
        
        this.status = StudyPlanStatus.COMPLETED;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 取消学习计划
     */
    public void cancel() {
        if (!status.canTransitionTo(StudyPlanStatus.CANCELLED)) {
            throw InvalidStudyPlanException.invalidStateTransition(status.getName(), StudyPlanStatus.CANCELLED.getName());
        }
        
        this.status = StudyPlanStatus.CANCELLED;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 判断是否属于指定用户
     */
    public boolean belongsToUser(UserId userId) {
        return Objects.equals(this.userId, userId);
    }
    
    /**
     * 判断是否属于指定类目
     */
    public boolean belongsToSpecificationType(SpecificationType specificationType) {
        return Objects.equals(this.specificationType, specificationType);
    }
    
    /**
     * 判断是否可以完成
     */
    public boolean canComplete() {
        return status.isInProgress() && 
               studyPeriod.isExpired() && 
               hasAchievedTargetMastery();
    }
    
    /**
     * 判断是否达到目标掌握程度
     */
    private boolean hasAchievedTargetMastery() {
        // 这里可以根据业务规则定义什么是"达到目标掌握程度"
        // 例如：达到"掌握"级别以上
        return degreeOfMastery.isHigherThan(DegreeOfMastery.UNDERSTAND) || 
               degreeOfMastery.equals(DegreeOfMastery.UNDERSTAND);
    }
    
    /**
     * 添加领域事件
     */
    public void addDomainEvent(DomainEvent event) {
        this.domainEvents.add(event);
    }
    
    /**
     * 获取领域事件列表（只读）
     */
    public List<DomainEvent> getDomainEvents() {
        return Collections.unmodifiableList(domainEvents);
    }
    
    /**
     * 清除领域事件
     */
    public void clearDomainEvents() {
        this.domainEvents.clear();
    }
    
    /**
     * 延长学习期间
     */
    public void extendStudyPeriod(StudyPeriod newPeriod) {
        if (newPeriod == null) {
            throw new IllegalArgumentException("学习期间不能为空");
        }
        if (newPeriod.getEndTime().isBefore(this.studyPeriod.getEndTime())) {
            throw new IllegalArgumentException("新的结束时间不能早于当前结束时间");
        }
        this.studyPeriod = newPeriod;
        this.updateTime = LocalDateTime.now();
    }
    
    /**
     * 判断学习计划是否已过期
     */
    public boolean isExpired() {
        return studyPeriod.isExpired();
    }
    


    private static void validateCreationParameters(SpecificationType specificationType,
                                                 UserId userId,
                                                 DegreeOfMastery degreeOfMastery,
                                                 StudyDuration dailyStudyDuration,
                                                 StudyPeriod studyPeriod) {
        if (specificationType == null) {
            throw new IllegalArgumentException("类目不能为空");
        }
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (degreeOfMastery == null) {
            throw new IllegalArgumentException("掌握程度不能为空");
        }
        if (dailyStudyDuration == null) {
            throw new IllegalArgumentException("每日学习时长不能为空");
        }
        if (studyPeriod == null) {
            throw new IllegalArgumentException("学习期间不能为空");
        }
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        StudyPlan studyPlan = (StudyPlan) o;
        return Objects.equals(id, studyPlan.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}